// ---------------------------------------------------------------------
//
// Copyright (c) 2020 - 2020 by the IBAMR developers
// All rights reserved.
//
// This file is part of IBAMR.
//
// IBAMR is free software and is distributed under the 3-clause BSD
// license. The full text of the license can be found in the file
// COPYRIGHT at the top level directory of IBAMR.
//
// ---------------------------------------------------------------------

/////////////////////////////// INCLUDE GUARD ////////////////////////////////

#ifndef included_IBTK_MergingLoadBalancer
#define included_IBTK_MergingLoadBalancer

/////////////////////////////// INCLUDES /////////////////////////////////////

#include <ibtk/config.h>

#include "ibtk/IBTK_MPI.h"
#include <ibtk/box_utilities.h>

#include <tbox/PIO.h>
#include <tbox/Pointer.h>

#include <Box.h>
#include <BoxArray.h>
#include <BoxList.h>
#include <LoadBalancer.h>

#include <algorithm>
#include <set>
#include <utility>
#include <vector>

namespace SAMRAI
{
namespace hier
{
class ProcessorMapping;
template <int DIM>
class PatchHierarchy;
} // namespace hier
} // namespace SAMRAI

/////////////////////////////// CLASS DEFINITION /////////////////////////////

namespace IBTK
{
/*!
 * \brief Class MergingLoadBalancer merges the boxes generated by a load
 * balancer in a final step to decrease the total number of boxes. In essence,
 * it postprocesses the list of boxes generated by its parent class to try and
 * coalesce the set of boxes on each process.
 *
 * @note During regridding, the boxes generated by this class are subsequently
 * read by GriddingAlgorithm, which will enforce minimum and maximum size
 * constraints; i.e., to take full advantage of this class one must set up the
 * GriddingAlgorithm objects to have very large maximum box sizes.
 */
class MergingLoadBalancer : public SAMRAI::mesh::LoadBalancer<NDIM>
{
public:
    // use parent constructor
    using SAMRAI::mesh::LoadBalancer<NDIM>::LoadBalancer;

    virtual void loadBalanceBoxes(SAMRAI::hier::BoxArray<NDIM>& out_boxes,
                                  SAMRAI::hier::ProcessorMapping& mapping,
                                  const SAMRAI::hier::BoxList<NDIM>& in_boxes,
                                  const SAMRAI::tbox::Pointer<SAMRAI::hier::PatchHierarchy<NDIM> > hierarchy,
                                  int level_number,
                                  const SAMRAI::hier::BoxArray<NDIM>& physical_domain,
                                  const SAMRAI::hier::IntVector<NDIM>& ratio_to_hierarchy_level_zero,
                                  const SAMRAI::hier::IntVector<NDIM>& min_size,
                                  const SAMRAI::hier::IntVector<NDIM>& max_size,
                                  const SAMRAI::hier::IntVector<NDIM>& cut_factor,
                                  const SAMRAI::hier::IntVector<NDIM>& bad_interval) const override;
};
} // namespace IBTK

//////////////////////////////////////////////////////////////////////////////

#endif //#ifndef included_IBTK_MergingLoadBalancer
